"""match font img using template."""

import heapq
import sys
from glob import glob
from os.path import join

from PIL import Image, ImageDraw, ImageFont

from cv_utils import RemoveMargin, UndistortResize, 

import matplotlib.pyplot as plt

import numpy as np

from tqdm import tqdm

sys.path = ['/home/hzh/.local/lib/python3.5/site-packages/'] + sys.path
import cv2

Width = 100
Height = 100
WHITE = 255


def show_img(title, img):
    """TODO: Docstring for show_img.

    :title: TODO
    :img: TODO
    :returns: TODO

    """
    plt.figure(title)
    plt.imshow(img)
    plt.show()


def show_imgs(imgs):
    sz = 100 + len(imgs)*10;
    plt.figure(1)
    # fig = plt.figure()
    for i, title_img in enumerate(imgs):
        t, im = title_img
        ax = plt.subplot(sz+i+1)
        plt.imshow(im)
        ax.title.set_text(t)
    plt.show()


class ChiTable:
    """chitable."""

    def __init__(self):
        """init."""
        with open('./data/chi3500.txt', 'r') as f:
            self.tbl_ = f.readline()

    def __getitem__(self, i):
        """Read font in utf-8."""
        return self.tbl_[i]

    def __len__(self):
        """How many fonts in this table."""
        return len(self.tbl_)

def get_channel(img):
    if len(img.shape) == 2:
        return 1
    else:
        return img.shape[2]

class TemplateMatcher:
    """match font image using templates."""

    def __init__(self, tmpl_dir):
        """Create chi, read tmpls."""
        self._std = Standarlizer()
        self.chi_tbl = ChiTable()
        self.tmpl_list = [None] * len(self.chi_tbl)
        print('loading tmmplates')
        for i in tqdm(range(len(self.chi_tbl))):
            fp = './data/font_tmpls/%d_0.png' % i
            im = cv2.imread(fp)
            im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
            # assert np.max(im) == 1, 'max pixle of image = %d != 1' % np.max(im)
            self.tmpl_list[i] = self._std(im)
        # show_img('tmpl', self.tmpl_list[111])

    def _match(self, tmpl, src):
        # cv2.imshow('match', np.hstack((tmpl, src)))
        # cv2.waitKey(0)
        a = np.sum(np.logical_and(src == WHITE, tmpl == WHITE))
        b = np.sum(src == WHITE)
        c = np.sum(tmpl == WHITE)
        return a*a / b / c

    def match_all(self, img):
        img = self._std(img)
        return [(self._match(t, img), i) for i, t in enumerate(self.tmpl_list)]

    def __call__(self, img):
        """obj(img)."""
        s, i = max(self.match_all(img))
        return (s, self.chi_tbl[i])


class Standarlizer:

    def __init__(self):
        self._process = [ToGray(),
                         Scalarify(),
                         RemoveMargin(),
                         UndistortResize(Width, Height)]

    def __call__(self, img):
        # l = []
        for p in self._process:
            img = p(img)
            # l.append((p.__class__.__name__, img))
        return img


def generate_font_templates():
    dst = './data/font_tmpls/'
    ttf = glob('./data/ttf/*.ttf')
    fonts = [ImageFont.truetype(t, Width) for t in ttf]
    chi = ChiTable()
    std = Standarlizer()
    for i in tqdm(range(len(chi))):
        for k, ft in enumerate(fonts):
            image = Image.new('RGB', (2*Width, 2*Height))
            draw = ImageDraw.Draw(image)
            x = Width/2
            y = Height/2
            draw.text((x, y), chi[i], font=ft)
            a = np.asarray(image)
            a = std(a)
            # a = cv2.cvtColor(a, cv2.COLOR_BGR2GRAY)
            # print("src dtype=", a.dtype)
            # a = remove_marg(a)
            # a = resize(a)
            # cv2.imshow("test", a)
            # cv2.waitKey(1000)
            # print("dst dtype=", a.dtype)
            cv2.imwrite(join(dst, '%d_%d.png' % (i, k)), a)
            # if i == 5:
                # show_img('dst', a)
                # break


class Evaluator:


    def __init__(self, debug=False):
        self._test_cnt = 0
        self._true_cnt = 0
        self._debug = debug
        if debug:
            self._fail_cases = []

    def __call__(self, expect, rst):
        self._test_cnt += 1
        if expect == rst[1]:
            self._true_cnt += 1
        elif self._debug:
            self._fail_cases.append('%s !=  %s' % (expect, rst[1]))
        return self

    def show_debug(self):
        print(self._fail_cases)

    def __str__(self):
        return 'eccuracy: %f' % (self._true_cnt / self._test_cnt)

def evaluate_model():
    matcher = TemplateMatcher('./data/font_tmpls/')
    chi_tbl = ChiTable()
    eva = Evaluator(debug=True)
    print("evaluating...")
    for i in tqdm(range(1, len(chi_tbl))):
        for j in range(1, 7):
            fp = './data/font_tmpls/%d_%d.png' % (i, j)
            im = cv2.imread(fp)
            rst = matcher(im)
            eva(chi_tbl[i], rst)
        if i % 100 == 0:
            print(eva)
    eva.show_debug()
    print(eva)


def debug_standarlizer():
    fp = './data/font_tmpls/333_1.png'
    a = cv2.imread(fp)
    b = Standarlizer()(a)
    show_imgs(b)


if '__main__' == __name__:
    # generate_font_templates()
    evaluate_model()
    # debug_standarlizer()
